home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Extensions / img / imgopmodule.c < prev    next >
Text File  |  1995-12-21  |  10KB  |  308 lines

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25.  
  26. #include "Python.h"
  27. #include "import.h"
  28.  
  29. /*
  30. ** An Order-8 ordered dithering matrix. Taken from netpbm, which in
  31. ** turn has it from "Digital Halftoning" by Robert Ulichney, MIT
  32. ** Press, ISBN 0-262-21009-6.
  33. */
  34.  
  35. static int dither8[16][16] = {
  36.       1,235, 59,219, 15,231, 55,215,  2,232, 56,216, 12,228, 52,212,
  37.     129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116,
  38.      33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244,
  39.     161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92,
  40.       9,225, 49,209,  5,239, 63,223, 10,226, 50,210,  6,236, 60,220,
  41.     137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124,
  42.      41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252,
  43.     169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86,
  44.       3,233, 57,217, 13,229, 53,213,  0,234, 58,218, 14,230, 54,214,
  45.     131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118,
  46.      35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246,
  47.     163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94,
  48.      11,227, 51,211,  7,237, 61,221,  8,224, 48,208,  4,238, 62,222,
  49.     139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126,
  50.      43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254,
  51.     171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84 };
  52.  
  53. static PyObject *errobject;
  54.  
  55. static PyObject *format_grey, *format_xgrey, *format_bitmap;
  56.  
  57. /*
  58. ** Get the relevant info from a format object:
  59. ** pixel size and alignment and bitpositions and masks for
  60. ** each component.
  61. */
  62. static int
  63. getfmtinfo(fmt, size, align, mr, mg, mb, sr, sg, sb)
  64.     PyObject *fmt;
  65.     int *size, *align, *mr, *mg, *mb, *sr, *sg, *sb;
  66. {
  67.     PyObject *dict, *value;
  68.     int ma, sa;
  69.     
  70.     if ( (dict=PyObject_GetAttrString(fmt, "descr")) == NULL )
  71.         return 0;
  72.  
  73.     if ( (value=PyDict_GetItemString(dict, "size")) == NULL )
  74.         return 0;
  75.     if ( (*size=PyInt_AsLong(value)) == -1 )
  76.         return 0;
  77.     if ( *size != 8 && *size != 16 && *size != 32 )
  78.         return 0;
  79.     *size /= 8;
  80.  
  81.     if ( (value=PyDict_GetItemString(dict, "align")) == NULL )
  82.         return 0;
  83.     if ( (*align=PyInt_AsLong(value)) == -1 )
  84.         return 0;
  85.     if ( *align != 8 && *align != 16 && *align != 32 )
  86.         return 0;
  87.     *align /= 8;
  88.     
  89.     if ( (value=PyDict_GetItemString(dict, "comp")) == NULL )
  90.         return 0;
  91.     *mr = *mg = *mb = *sr = *sg = *sb = ma = sa = 0;
  92.     if ( !PyArg_ParseTuple(value, "(ii)|(ii)(ii)(ii)",
  93.                    sr, mr, sg, mg, sb, mb, &sa, &ma) )
  94.         return 0;
  95.     *mr = (1<<*mr) - 1;
  96.     *mg = (1<<*mg) - 1;
  97.     *mb = (1<<*mb) - 1;
  98.     
  99.     Py_DECREF(dict);
  100.     return 1;
  101. }
  102.  
  103. static char doc_shuffle[] =
  104.     "Re-arrange component bits in pixels.\n"
  105.     "Args: (data, width, height, source_format, result_format)\n"
  106.     "Returns: string containing shuffled pixel data";
  107.  
  108. static PyObject *
  109. imo_shuffle(self, args)
  110.     PyObject *self;
  111.     PyObject *args;
  112. {
  113.     PyObject *srcfmt, *dstfmt;
  114.     unsigned char *srcp8, *dstp8;
  115.     unsigned short *srcp16, *dstp16;
  116.     unsigned long *srcp32, *dstp32;
  117.     unsigned long srcpixel, dstpixel, comp;
  118.     int srcalign, dstalign;
  119.     int srcsize, dstsize;
  120.     int smr, smg, smb, ssr, ssg, ssb, dmr, dmg, dmb, dsr, dsg, dsb;
  121.     PyObject *rv;
  122.     int w, rowlen, h, size, x, y;
  123.     
  124.     if (!PyArg_ParseTuple(args, "s#iiOO", &srcp8, &size, &w, &h,
  125.                   &srcfmt, &dstfmt))
  126.         return NULL;
  127.     
  128.     /*
  129.     ** Get the relevant info from the format objects, do some argument
  130.     **  checking and allocate the result buffer.
  131.     */
  132.     if (!getfmtinfo(srcfmt, &srcsize, &srcalign, &smr, &smg, &smb,
  133.             &ssr, &ssg, &ssb) ||
  134.         !getfmtinfo(dstfmt, &dstsize, &dstalign, &dmr, &dmg,
  135.                 &dmb, &dsr, &dsg, &dsb) ) {
  136.         PyErr_SetString(errobject, "Invalid format-object");
  137.         return NULL;
  138.     }
  139.     rowlen = (w*srcsize+srcalign-1) & ~(srcalign-1);
  140.     if ( rowlen*h != size ) {
  141.         PyErr_SetString(errobject, "Incorrectly sized data");
  142.         return NULL;
  143.     }
  144.     
  145.     rowlen = (w*dstsize+dstalign-1) & ~(dstalign-1);
  146.     if ( (rv=PyString_FromStringAndSize((char *)0, rowlen*h)) == 0 )
  147.         return NULL;
  148.     dstp8 = (unsigned char *)PyString_AsString(rv);
  149.     
  150.     dstp16 = (unsigned short *)dstp8;
  151.     dstp32 = (unsigned long *)dstp8;
  152.     srcp16 = (unsigned short *)srcp8;
  153.     srcp32 = (unsigned long *)srcp8;
  154.     
  155.     for( y=0; y<h; y++) {
  156.         for( x=0; x<w; x++ ) {
  157.             
  158.             /* Get the source pixel into srcpixel */
  159.             if ( srcsize==1 ) srcpixel = *srcp8++; else
  160.             if ( srcsize==2 ) srcpixel = *srcp16++; else
  161.                               srcpixel = *srcp32++;
  162.             
  163.             dstpixel = 0;
  164.             
  165.             /* For each existing (and wanted) component,
  166.             **grab/scale/insert it
  167.             */
  168.             if ( smr && dmr ) {
  169.                 comp = (srcpixel >> ssr) & smr;    /* Get  bits */
  170.                 comp = (comp*dmr)/smr; /* convert magnitude */
  171.                 dstpixel = dstpixel | (comp<<dsr); /* Insert */
  172.             }
  173.             if ( smg && dmg ) {
  174.                 comp = (srcpixel >> ssg) & smg;
  175.                 comp = (comp*dmg)/smg;
  176.                 dstpixel = dstpixel | (comp << dsg);
  177.             }
  178.             if ( smb && dmb ) {
  179.                 comp = (srcpixel >> ssb) & smb;
  180.                 comp = (comp*dmb)/smb;
  181.                 dstpixel = dstpixel | (comp << dsb);
  182.             }
  183.             
  184.             /* And put the result in the output buffer,
  185.             **in the correct size
  186.             */
  187.             if ( dstsize==1 ) *dstp8++ = dstpixel; else
  188.             if ( dstsize==2 ) *dstp16++ = dstpixel; else
  189.                               *dstp32++ = dstpixel;
  190.         }
  191.         /* Finally, do end-of-row alignment. Note that this code works
  192.         ** because we have checked that size and align are 1, 2 or 4,
  193.         ** nothing else.
  194.         */
  195.         if ( srcalign > srcsize ) {
  196.             if ( srcsize==1 )
  197.                 while( (long)srcp8 & (srcalign-1) ) srcp8++;
  198.             else if ( srcsize==2 )
  199.                 while( (long)srcp16 & (srcalign-1) ) srcp16++;
  200.             else
  201.                 while( (long)srcp32 & (srcalign-1) ) srcp32++;
  202.         }
  203.         if ( dstalign > dstsize ) {
  204.             if ( dstsize==1 )
  205.                 while( (long)dstp8 & (dstalign-1) )
  206.                     *dstp8++ = 0;
  207.             else if ( srcsize==2 )
  208.                 while( (long)dstp16 & (dstalign-1) )
  209.                     *dstp16++ = 0;
  210.             else
  211.                 while( (long)dstp32 & (dstalign-1) )
  212.                     *dstp32++ = 0;
  213.         }
  214.     }
  215.     return rv;
  216. }
  217.  
  218. static char doc_dither[] = 
  219.     "Dither greyscale to bitmap using an order-8 ordered dither.\n"
  220.     "Args: (data, width, height, source_format, result_format)\n"
  221.     "Returns: string containing bitmap data";
  222.  
  223. static PyObject *
  224. imo_dither(self, args)
  225.     PyObject *self;
  226.     PyObject *args;
  227. {
  228.     PyObject *srcfmt, *dstfmt;
  229.     PyObject *rv;
  230.     unsigned char *srcdata, *dstdata;
  231.     int x, y, h, w, rowlen, size;
  232.  
  233. #define _SRC(x, y) (srcdata[((y)*rowlen)+(x)])
  234. #define _DST(x, y) (dstdata[((y)*w)+(x)])
  235.     
  236.  
  237.     if ( !PyArg_ParseTuple(args, "s#iiOO", &srcdata, &size, &w, &h,
  238.                &srcfmt, &dstfmt) )
  239.     return NULL;
  240.     if ( (srcfmt != format_xgrey && srcfmt != format_grey) ||
  241.     dstfmt != format_bitmap ) {
  242.     PyErr_SetString(errobject,
  243.             "Only supporting (x)grey to pbmbitmap currently");
  244.     return NULL;
  245.     }
  246.  
  247.     if (srcfmt == format_grey )
  248.     rowlen = (w+3) & ~3;
  249.     else
  250.     rowlen = w;
  251.     if ( size != rowlen*h ) {
  252.     PyErr_SetString(errobject, "Incorrect data size");
  253.     return NULL;
  254.     }
  255.     if( (rv=PyString_FromStringAndSize((char *)0, w*h)) == NULL )
  256.     return NULL;
  257.     dstdata = (unsigned char *)PyString_AsString(rv);
  258.     for(y=0; y<w; y++)
  259.     for(x=0; x<h; x++)
  260.         if ( _SRC(x, y) >= dither8[y&0xf][x&0xf] )
  261.         _DST(x, y) = 1;
  262.         else
  263.         _DST(x, y) = 0;
  264.     return rv;
  265. }
  266.  
  267. /* List of functions defined in the module */
  268.  
  269. static struct PyMethodDef xxx_module_methods[] = {
  270.     {"shuffle",    imo_shuffle,    1,    doc_shuffle},
  271.     {"dither",    imo_dither,    1,    doc_dither},
  272.     {NULL,        NULL}        /* sentinel */
  273. };
  274.  
  275.  
  276. /* Initialization function for the module (*must* be called initimgxxx) */
  277. static char doc_imgop[] = "Various operations on images";
  278.  
  279. void
  280. initimgop()
  281. {
  282.     PyObject *m, *d, *x, *formatmodule, *formatdict;
  283.  
  284.     /* Create the module and add the functions */
  285.     m = Py_InitModule("imgop", xxx_module_methods);
  286.  
  287.     /* Add some symbolic constants to the module */
  288.     d = PyModule_GetDict(m);
  289.     errobject = PyString_FromString("imgop.error");
  290.     PyDict_SetItemString(d, "error", errobject);
  291.     x = PyString_FromString(doc_imgop);
  292.     PyDict_SetItemString(d, "__doc__", x);
  293.  
  294.     /* Get supported formats */
  295.     if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
  296.         Py_FatalError("imgxxx depends on imgformat");
  297.     if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
  298.         Py_FatalError("imgformat has no dict");
  299.  
  300.     format_grey = PyDict_GetItemString(formatdict,"grey");
  301.     format_xgrey = PyDict_GetItemString(formatdict,"xgrey");
  302.     format_bitmap = PyDict_GetItemString(formatdict,"pbmbitmap");
  303.  
  304.     /* Check for errors */
  305.     if (PyErr_Occurred())
  306.         Py_FatalError("can't initialize module imgop");
  307. }
  308.